package com.datagateway.component;

import com.fasterxml.jackson.databind.ObjectMapper;
import com.fasterxml.jackson.dataformat.avro.AvroMapper;
import com.fasterxml.jackson.dataformat.protobuf.ProtobufMapper;
import com.fasterxml.jackson.dataformat.xml.XmlMapper;
import com.fasterxml.jackson.dataformat.yaml.YAMLMapper;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;

import java.io.IOException;
import java.util.concurrent.atomic.AtomicLong;

/**
 * 数据序列化管理器
 * 支持多种序列化格式，优化数据传输和存储
 * 
 * @author Data Gateway Team
 * @version 1.0.0
 */
@Component
public class DataSerializationManager {

    private static final Logger logger = LoggerFactory.getLogger(DataSerializationManager.class);

    /**
     * 序列化格式枚举
     */
    public enum SerializationFormat {
        JSON("json"),
        XML("xml"),
        YAML("yaml"),
        AVRO("avro"),
        PROTOBUF("protobuf"),
        BINARY("binary");

        private final String name;

        SerializationFormat(String name) {
            this.name = name;
        }

        public String getName() {
            return name;
        }
    }

    @Autowired
    private ObjectMapper jsonMapper;

    @Autowired
    private XmlMapper xmlMapper;

    @Autowired
    private YAMLMapper yamlMapper;

    /**
     * 序列化统计信息
     */
    private final AtomicLong totalSerializationCount = new AtomicLong(0);
    private final AtomicLong totalDeserializationCount = new AtomicLong(0);
    private final AtomicLong totalSerializedBytes = new AtomicLong(0);
    private final AtomicLong totalOriginalBytes = new AtomicLong(0);

    /**
     * 默认序列化格式
     */
    private SerializationFormat defaultFormat = SerializationFormat.JSON;

    /**
     * 序列化对象
     * 
     * @param object 要序列化的对象
     * @param format 序列化格式
     * @return 序列化后的字节数组
     */
    public byte[] serialize(Object object, SerializationFormat format) {
        if (object == null) {
            return new byte[0];
        }

        long startTime = System.currentTimeMillis();
        
        try {
            byte[] serializedData = doSerialize(object, format);
            
            long processingTime = System.currentTimeMillis() - startTime;
            long originalSize = getObjectSize(object);
            long serializedSize = serializedData.length;
            
            // 更新统计信息
            totalSerializationCount.incrementAndGet();
            totalSerializedBytes.addAndGet(serializedSize);
            totalOriginalBytes.addAndGet(originalSize);
            
            logger.debug("对象序列化完成: 格式={}, 原始大小={} bytes, 序列化后大小={} bytes, 耗时={} ms", 
                        format.getName(), originalSize, serializedSize, processingTime);
            
            return serializedData;
            
        } catch (Exception e) {
            logger.error("对象序列化失败: 格式={}, 对象类型={}", format.getName(), object.getClass().getSimpleName(), e);
            throw new RuntimeException("对象序列化失败", e);
        }
    }

    /**
     * 序列化对象（使用默认格式）
     * 
     * @param object 要序列化的对象
     * @return 序列化后的字节数组
     */
    public byte[] serialize(Object object) {
        return serialize(object, defaultFormat);
    }

    /**
     * 反序列化对象
     * 
     * @param data 序列化后的数据
     * @param targetClass 目标类型
     * @param format 序列化格式
     * @return 反序列化后的对象
     */
    public <T> T deserialize(byte[] data, Class<T> targetClass, SerializationFormat format) {
        if (data == null || data.length == 0) {
            return null;
        }

        long startTime = System.currentTimeMillis();
        
        try {
            T deserializedObject = doDeserialize(data, targetClass, format);
            
            long processingTime = System.currentTimeMillis() - startTime;
            long dataSize = data.length;
            
            // 更新统计信息
            totalDeserializationCount.incrementAndGet();
            
            logger.debug("对象反序列化完成: 格式={}, 数据大小={} bytes, 目标类型={}, 耗时={} ms", 
                        format.getName(), dataSize, targetClass.getSimpleName(), processingTime);
            
            return deserializedObject;
            
        } catch (Exception e) {
            logger.error("对象反序列化失败: 格式={}, 目标类型={}, 数据大小={} bytes", 
                        format.getName(), targetClass.getSimpleName(), data.length, e);
            throw new RuntimeException("对象反序列化失败", e);
        }
    }

    /**
     * 反序列化对象（使用默认格式）
     * 
     * @param data 序列化后的数据
     * @param targetClass 目标类型
     * @return 反序列化后的对象
     */
    public <T> T deserialize(byte[] data, Class<T> targetClass) {
        return deserialize(data, targetClass, defaultFormat);
    }

    /**
     * 执行序列化
     * 
     * @param object 要序列化的对象
     * @param format 序列化格式
     * @return 序列化后的字节数组
     */
    private byte[] doSerialize(Object object, SerializationFormat format) throws IOException {
        switch (format) {
            case JSON:
                return jsonMapper.writeValueAsBytes(object);
            case XML:
                return xmlMapper.writeValueAsBytes(object);
            case YAML:
                return yamlMapper.writeValueAsBytes(object);
            case AVRO:
                return serializeWithAvro(object);
            case PROTOBUF:
                return serializeWithProtobuf(object);
            case BINARY:
                return serializeWithBinary(object);
            default:
                throw new IllegalArgumentException("不支持的序列化格式: " + format);
        }
    }

    /**
     * 执行反序列化
     * 
     * @param data 序列化后的数据
     * @param targetClass 目标类型
     * @param format 序列化格式
     * @return 反序列化后的对象
     */
    private <T> T doDeserialize(byte[] data, Class<T> targetClass, SerializationFormat format) throws IOException {
        switch (format) {
            case JSON:
                return jsonMapper.readValue(data, targetClass);
            case XML:
                return xmlMapper.readValue(data, targetClass);
            case YAML:
                return yamlMapper.readValue(data, targetClass);
            case AVRO:
                return deserializeWithAvro(data, targetClass);
            case PROTOBUF:
                return deserializeWithProtobuf(data, targetClass);
            case BINARY:
                return deserializeWithBinary(data, targetClass);
            default:
                throw new IllegalArgumentException("不支持的序列化格式: " + format);
        }
    }

    /**
     * 使用Avro序列化
     */
    private byte[] serializeWithAvro(Object object) throws IOException {
        // 简化实现，实际项目中应使用真正的Avro库
        logger.warn("Avro序列化使用JSON替代实现，建议使用真正的Avro库");
        return jsonMapper.writeValueAsBytes(object);
    }

    /**
     * 使用Avro反序列化
     */
    private <T> T deserializeWithAvro(byte[] data, Class<T> targetClass) throws IOException {
        // 简化实现，实际项目中应使用真正的Avro库
        logger.warn("Avro反序列化使用JSON替代实现，建议使用真正的Avro库");
        return jsonMapper.readValue(data, targetClass);
    }

    /**
     * 使用Protobuf序列化
     */
    private byte[] serializeWithProtobuf(Object object) throws IOException {
        // 简化实现，实际项目中应使用真正的Protobuf库
        logger.warn("Protobuf序列化使用JSON替代实现，建议使用真正的Protobuf库");
        return jsonMapper.writeValueAsBytes(object);
    }

    /**
     * 使用Protobuf反序列化
     */
    private <T> T deserializeWithProtobuf(byte[] data, Class<T> targetClass) throws IOException {
        // 简化实现，实际项目中应使用真正的Protobuf库
        logger.warn("Protobuf反序列化使用JSON替代实现，建议使用真正的Protobuf库");
        return jsonMapper.readValue(data, targetClass);
    }

    /**
     * 使用二进制序列化
     */
    private byte[] serializeWithBinary(Object object) throws IOException {
        // 使用Java原生序列化
        try (java.io.ByteArrayOutputStream baos = new java.io.ByteArrayOutputStream();
             java.io.ObjectOutputStream oos = new java.io.ObjectOutputStream(baos)) {
            
            oos.writeObject(object);
            oos.flush();
            return baos.toByteArray();
        }
    }

    /**
     * 使用二进制反序列化
     */
    private <T> T deserializeWithBinary(byte[] data, Class<T> targetClass) throws IOException, ClassNotFoundException {
        // 使用Java原生反序列化
        try (java.io.ByteArrayInputStream bais = new java.io.ByteArrayInputStream(data);
             java.io.ObjectInputStream ois = new java.io.ObjectInputStream(bais)) {
            
            return targetClass.cast(ois.readObject());
        }
    }

    /**
     * 获取对象大小（估算）
     * 
     * @param object 对象
     * @return 估算大小
     */
    private long getObjectSize(Object object) {
        if (object == null) {
            return 0;
        }
        
        try {
            // 使用JSON序列化来估算对象大小
            byte[] jsonBytes = jsonMapper.writeValueAsBytes(object);
            return jsonBytes.length;
        } catch (Exception e) {
            // 如果无法序列化，返回一个估算值
            return 100; // 默认估算值
        }
    }

    /**
     * 设置默认序列化格式
     * 
     * @param format 序列化格式
     */
    public void setDefaultFormat(SerializationFormat format) {
        this.defaultFormat = format;
        logger.info("默认序列化格式已更新: {}", format.getName());
    }

    /**
     * 获取默认序列化格式
     * 
     * @return 序列化格式
     */
    public SerializationFormat getDefaultFormat() {
        return defaultFormat;
    }

    /**
     * 获取序列化统计信息
     * 
     * @return 统计信息
     */
    public SerializationStatistics getStatistics() {
        long totalSerialized = totalSerializedBytes.get();
        long totalOriginal = totalOriginalBytes.get();
        double averageSerializationRatio = totalOriginal > 0 ? (double) totalSerialized / totalOriginal : 0;
        
        return new SerializationStatistics(
            totalSerializationCount.get(),
            totalDeserializationCount.get(),
            totalOriginal,
            totalSerialized,
            averageSerializationRatio,
            defaultFormat,
            System.currentTimeMillis()
        );
    }

    /**
     * 重置统计信息
     */
    public void resetStatistics() {
        totalSerializationCount.set(0);
        totalDeserializationCount.set(0);
        totalSerializedBytes.set(0);
        totalOriginalBytes.set(0);
        logger.info("序列化统计信息已重置");
    }

    /**
     * 序列化统计信息类
     */
    public static class SerializationStatistics {
        private final long totalSerializationCount;
        private final long totalDeserializationCount;
        private final long totalOriginalBytes;
        private final long totalSerializedBytes;
        private final double averageSerializationRatio;
        private final SerializationFormat defaultFormat;
        private final long timestamp;

        public SerializationStatistics(long totalSerializationCount, long totalDeserializationCount,
                                     long totalOriginalBytes, long totalSerializedBytes,
                                     double averageSerializationRatio, SerializationFormat defaultFormat,
                                     long timestamp) {
            this.totalSerializationCount = totalSerializationCount;
            this.totalDeserializationCount = totalDeserializationCount;
            this.totalOriginalBytes = totalOriginalBytes;
            this.totalSerializedBytes = totalSerializedBytes;
            this.averageSerializationRatio = averageSerializationRatio;
            this.defaultFormat = defaultFormat;
            this.timestamp = timestamp;
        }

        // Getter方法
        public long getTotalSerializationCount() { return totalSerializationCount; }
        public long getTotalDeserializationCount() { return totalDeserializationCount; }
        public long getTotalOriginalBytes() { return totalOriginalBytes; }
        public long getTotalSerializedBytes() { return totalSerializedBytes; }
        public double getAverageSerializationRatio() { return averageSerializationRatio; }
        public SerializationFormat getDefaultFormat() { return defaultFormat; }
        public long getTimestamp() { return timestamp; }
        
        public long getTotalBytesSaved() { return totalOriginalBytes - totalSerializedBytes; }
        public double getSerializationEfficiency() { return 1.0 - averageSerializationRatio; }
    }
}
